package yourapp.expense.main;

import yourapp.expense.dao.CategoryDAO;
import yourapp.expense.dao.ExpenseDAO;
import yourapp.expense.dto.StatisticsDTO;
import yourapp.expense.entity.*;
import yourapp.expense.service.ExpenseService;
import yourapp.expense.service.QueryService;
import yourapp.expense.util.DateListUtil;
import yourapp.expense.util.ExpensePrinter;
import yourapp.expense.util.InputValidator;
import yourapp.expense.util.DateUtil;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

public class ConsoleUI {

  private Scanner scanner;
  private CategoryDAO categoryDAO;
  private ExpenseService expenseService;
  private InputValidator inputValidator;
  private DateUtil dateUtil;
  private QueryService queryService = new QueryService();
  public ConsoleUI() {
    this.scanner = new Scanner(System.in);
    this.categoryDAO = new CategoryDAO();
    this.expenseService = new ExpenseService();
    this.inputValidator = new InputValidator();
    this.dateUtil = new DateUtil();
  }

  /**
   * 显示主菜单，包括添加记录和退出选项
   */
  public void showMainMenu() {
    System.out.println("===== 主菜单 =====");
    System.out.println("1. 添加记录");
    System.out.println("2. 查看最近记录");
    System.out.println("3. 删除一条记录");
    System.out.println("4. 修改一条记录");
    System.out.println("5. 按日期查看记录");
    System.out.println("6. 按日期统计支出");
    System.out.println("0. 退出");
    System.out.print("请选择: ");
  }

  /**
   * 获取用户选择的菜单项
   * @return 用户选择的选项
   */
  public int getUserChoice() {
    return scanner.nextInt();
  }

  /**
   * 处理添加支出记录的逻辑
   */
  public void handleAddExpense() {
    // 列出用途分类表
    List<PurposeCategory> purposeCategories = categoryDAO.getAllPurposeCategories();
    System.out.println("===== 用途分类 =====");
    for (PurposeCategory pc : purposeCategories) {
      System.out.println(pc.getPurposeCategoryId() + ". " + pc.getName());
    }

    int purposeCategoryId = getSafeIntInput("请选择用途分类ID");
    scanner.nextLine(); // 清除缓冲区

    // 列出支付软件表
    List<PaymentAppCategory> paymentAppCategories = categoryDAO.getAllPaymentAppCategories();
    System.out.println("===== 支付软件分类 =====");
    for (PaymentAppCategory pac : paymentAppCategories) {
      System.out.println(pac.getPaymentAppCategoryId() + ". " + pac.getName());
    }
    System.out.print("请选择支付软件分类ID (可选，直接回车跳过): ");
    String paymentInput = scanner.nextLine().trim();
    Integer paymentAppCategoryId = null;
    if (!paymentInput.isEmpty()) {
      paymentAppCategoryId = Integer.parseInt(paymentInput);
    }
    // 列出购物软件分类表
    List<ShoppingAppCategory> shoppingAppCategories = categoryDAO.getAllShoppingAppCategories();
    System.out.println("===== 购物软件分类 =====");
    for (ShoppingAppCategory sac : shoppingAppCategories) {
      System.out.println(sac.getShoppingAppCategoryId() + ". " + sac.getName());
    }
    System.out.print("请选择购物软件分类ID (可选，直接回车跳过): ");
    String shoppingInput = scanner.nextLine().trim();
    Integer shoppingAppCategoryId = null;
    if (!shoppingInput.isEmpty()) {
      shoppingAppCategoryId = Integer.parseInt(shoppingInput);
    }
    // 输入描述
    System.out.print("请输入描述: ");
    String description = scanner.nextLine().trim();

    // 输入费用
    System.out.print("请输入费用: ");
    String amountStr = scanner.nextLine().trim();
    while (!inputValidator.validateAmount(amountStr)) {
      System.out.print("费用无效，请重新输入费用: ");
      amountStr = scanner.nextLine();
    }
    BigDecimal amount = new BigDecimal(amountStr);

    // 输入日期
    System.out.print("请输入日期 (yyyy-MM-dd): ");
    String dateStr = scanner.nextLine().trim();
    while (!inputValidator.validateDate(dateStr)) {
      System.out.print("日期格式无效，请重新输入日期 (yyyy-MM-dd): ");
      dateStr = scanner.nextLine();
    }
    Date expenseDate = null;

    expenseDate = dateUtil.parseDate(dateStr);


    // 获取用途分类对象
    PurposeCategory purposeCategory = null;
    for (PurposeCategory pc : purposeCategories) {
      if (pc.getPurposeCategoryId() == purposeCategoryId) {
        purposeCategory = pc;
        break;
      }
    }

    // 获取支付软件分类对象
    PaymentAppCategory paymentAppCategory = null;
    if (paymentAppCategoryId != null) {
      for (PaymentAppCategory pac : paymentAppCategories) {
        if (pac.getPaymentAppCategoryId() == paymentAppCategoryId) {
          paymentAppCategory = pac;
          break;
        }
      }
    }
    // 获取购物软件分类对象
    ShoppingAppCategory shoppingAppCategory = null;
    if (shoppingAppCategoryId != null) {
      for (ShoppingAppCategory sac : shoppingAppCategories) {
        if (sac.getShoppingAppCategoryId() == shoppingAppCategoryId) {
          shoppingAppCategory = sac;
          break;
        }
      }
    }

    // 创建 Expense 对象
    Expense expense = new Expense(amount, expenseDate, description, paymentAppCategory, shoppingAppCategory, purposeCategory);

    // 调用 ExpenseService 添加支出记录
    expenseService.addExpense(expense);
    System.out.println("===== 记录添加成功 =====");
  }
  //02显示最近的八条支出记录
  public void showRecentExpenses() {
    List<Expense> recentExpenses = expenseService.getRecentExpenses();
    System.out.println("= 最近八条支出记录 =");
    for (Expense expense : recentExpenses) {
      ExpensePrinter.printExpenseDetails(expense);
    }
  }
  //03删除一条记录
  public void handleDeleteExpense() {

    int expenseId = getSafeIntInput("请输入记录 id：");
    scanner.nextLine(); // 清除缓冲区

    // 获取记录信息
    Expense expense = expenseService.getExpenseById(expenseId);
    if (expense == null) {
      System.out.println("未找到该记录！");
      return;
    }

    // 打印记录信息
    System.out.printf("找到记录：ID=%d, 金额=%.2f, 日期=%s, 描述=%s%n",
        expense.getExpenseId(),
        expense.getAmount(),
        expense.getExpenseDate(),
        expense.getDescription());

    // 确认删除
    System.out.print("确定删除这条记录吗？（y or n）：");
    String confirm = scanner.nextLine().trim().toLowerCase();
    if (confirm.equals("y")) {
      expenseService.deleteExpense(expenseId);
      System.out.println("记录已删除。");
    } else {
      System.out.println("取消删除。");
    }
  }
  //04 修改一条记录
  public void handleModifyExpense() {
    int expenseId = getSafeIntInput("请输入记录 id：");
    scanner.nextLine(); // 清除缓冲区

    Expense expense = expenseService.getViewById(expenseId);
    if (expense == null) {
      System.out.println("未找到该记录！");
      return;
    }

    ExpensePrinter.printExpenseDetails(expense);//输出这行记录

    System.out.println("输出选项：");
    System.out.println("1.amount");
    System.out.println("2.expenseDate");
    System.out.println("3.description");
    System.out.println("4.paymentAppCategory");
    System.out.println("5.shoppingAppCategory");
    System.out.println("6.purposeCategory");

    int fieldChoice = getSafeIntInput("修改哪个字段？（1~6）：");
    scanner.nextLine(); // 清除缓冲区

    switch (fieldChoice) {
      case 1:
        String amountStr = getNewInput("请输入新的金额: ");
        expense.setAmount(new BigDecimal(amountStr));
        expenseService.updateExpenseField(expense, 1);
        break;
      case 2:
        String dateStr = getNewInput("请输入新的日期 (yyyy-MM-dd): ");
        expense.setExpenseDate(dateUtil.parseDate(dateStr));
        expenseService.updateExpenseField(expense, 2);
        break;
      case 3:
        String desc = getNewInput("请输入新的描述: ");
        expense.setDescription(desc);
        expenseService.updateExpenseField(expense, 3);
        break;
      case 4:
        List<PaymentAppCategory> paymentCategories = categoryDAO.getAllPaymentAppCategories();
        for (PaymentAppCategory pac : paymentCategories) {
          System.out.println(pac.getPaymentAppCategoryId() + ". " + pac.getName());
        }
        String paymentInput = getNewInput("请选择新的支付软件分类ID (可选，直接回车跳过): ");
        if (!paymentInput.isEmpty()) {
          int paymentId = Integer.parseInt(paymentInput);
          expense.setPaymentAppCategory(new PaymentAppCategory(paymentId, ""));
        } else {
          expense.setPaymentAppCategory(null);
        }
        expenseService.updateExpenseField(expense, 4);
        break;

      case 5:
        List<ShoppingAppCategory> shoppingCategories = categoryDAO.getAllShoppingAppCategories();
        for (ShoppingAppCategory sac : shoppingCategories) {
          System.out.println(sac.getShoppingAppCategoryId() + ". " + sac.getName());
        }
        String shoppingInput = getNewInput("请选择新的购物软件分类ID (可选，直接回车跳过): ");
        if (!shoppingInput.isEmpty()) {
          int shoppingId = Integer.parseInt(shoppingInput);
          expense.setShoppingAppCategory(new ShoppingAppCategory(shoppingId, ""));
        } else {
          expense.setShoppingAppCategory(null);
        }
        expenseService.updateExpenseField(expense, 5);
        break;

      case 6:
        List<PurposeCategory> purposeCategories = categoryDAO.getAllPurposeCategories();
        for (PurposeCategory pc : purposeCategories) {
          System.out.println(pc.getPurposeCategoryId() + ". " + pc.getName());
        }
        String purposeInput = getNewInput("请选择新的用途分类ID (可选，直接回车跳过): ");
        if (!purposeInput.isEmpty()) {
          int purposeId = Integer.parseInt(purposeInput);
          expense.setPurposeCategory(new PurposeCategory(purposeId, ""));
        } else {
          expense.setPurposeCategory(null);
        }
        expenseService.updateExpenseField(expense, 6);
        break;
      default:
        System.out.println("无效选择！");
    }

    System.out.println("修改成功");
    Expense updatedExpense = expenseService.getViewById(expenseId);
    ExpensePrinter.printExpenseDetails(expense);//输出这行记录
  }
  // ConsoleUI.java 新增方法
  //05按日期查看记录
  public void handleQueryByDate() {
    int year = getSafeIntInput("输入年份：");
    List<Expense> yearlyExpenses = new QueryService().queryExpensesByYear(year);
    System.out.println(year + "年记录：");
    if (yearlyExpenses.isEmpty()) {
      System.out.println("该年没有支出记录");
    } else if (yearlyExpenses.size() > 20) {
      System.out.println("数量太多需下载查看");
    } else {
      System.out.print("是否查看该年所有记录？(y/n): ");
      String choice = scanner.nextLine().trim().toLowerCase();
      if (choice.equals("y")) {
        for (Expense expense : yearlyExpenses) {
          ExpensePrinter.printExpenseDetails(expense);
        }
      }
    }

    int month = getSafeIntInput("输入月份（输入 0 退回一级菜单）：");
    if (month == 0) {
      return;
    }
    List<Expense> monthlyExpenses = new QueryService().queryExpensesByMonth(year, month);
    System.out.println(year + "年" + month + "月记录：");
    if (monthlyExpenses.isEmpty()) {
      System.out.println("该月没有支出记录");
    } else if (monthlyExpenses.size() > 20) {
      System.out.println("数量太多需下载查看");
    } else {
      System.out.print("是否查看该月所有记录？(y/n): ");
      String choice = scanner.nextLine().trim().toLowerCase();
      if (choice.equals("y")) {
        for (Expense expense : monthlyExpenses) {
          ExpensePrinter.printExpenseDetails(expense);
        }
      }
    }

    int day = getSafeIntInput("输入日期（输入 0 退回一级菜单）：");
    if (day == 0) {
      return;
    }
    List<Expense> dailyExpenses = new QueryService().queryExpensesByDay(year, month, day);
    System.out.println(year + "年" + month + "月" + day + "日记录：");
    if (dailyExpenses.isEmpty()) {
      System.out.println("该日没有支出记录");
    } else if (dailyExpenses.size() > 20) {
      System.out.println("数量太多需下载查看");
    } else {
      System.out.print("是否查看该日所有记录？(y/n): ");
      String choice = scanner.nextLine().trim().toLowerCase();
      if (choice.equals("y")) {
        for (Expense expense : dailyExpenses) {
          ExpensePrinter.printExpenseDetails(expense);
        }
      }
    }
  }
  //新增代码
  //06按日期统计支出
  public void handleQueryByDateStatistics() {
    int option = getSafeIntInput("1.按年 2.按月 3.按周 0.回退");
    if (option == 0) return;

    if (option == 1) {
      int year = getSafeIntInput("输入年份：");
      StatisticsDTO stats = this.queryService.calculateYearStats(year);
      printStats(stats);
    } else if (option == 2) {
      int year = getSafeIntInput("输入年份：");
      int month = getSafeIntInput("输入月份：");
      StatisticsDTO stats = this.queryService.calculateMonthStats(year, month);
      printStats(stats);
    } else if (option == 3) {
      int weekOption = getSafeIntInput("1.这周 2.上周 3.上上周 0.回退");
      if (weekOption == 0) return;
      List<java.sql.Date> dates = DateListUtil.getDateList(weekOption);
      StatisticsDTO stats = this.queryService.calculateWeekStats(dates);
      printStats(stats);
    }
    else{
      System.out.println("无效选择");
    }
  }
  //打印统计结果
  private void printStats(StatisticsDTO stats) {
    ExpensePrinter.printExpenseDetails(stats.getMaxExpense());
    ExpensePrinter.printExpenseDetails(stats.getMinExpense());
    System.out.printf("平均值: %.2f%n", stats.getAvgAmount().doubleValue());
  }


  /**
   * 运行主程序循环
   */
  public void run() {
    int choice;
    do {
      showMainMenu();
      choice = getUserChoice();
      switch (choice) {
        case 1:
          handleAddExpense();
          break;
        case 2:
          showRecentExpenses();
          break;
        case 3:
          handleDeleteExpense();
          break;
        case 4:
          handleModifyExpense();
          break;
        case 5:
          handleQueryByDate();
          break;
        case 6:
          handleQueryByDateStatistics();
          break;
        case 0:
          System.out.println("退出程序。");
          break;
        default:
          System.out.println("无效选择，请重试。");
      }
    } while (choice != 0);
  }
  //代码块封装
  public int getSafeIntInput(String prompt) {
    System.out.print(prompt);
    String input = scanner.nextLine().trim();
    while (!input.matches("\\d+")) {  // 只允许数字
      input = scanner.nextLine().trim();
    }
    return Integer.parseInt(input);
  }

  public String getNewInput(String promt) {
    System.out.print(promt);
    return scanner.nextLine().trim();
  }

  public static void main(String[] args) {
    ConsoleUI consoleUI = new ConsoleUI();
    consoleUI.run();
  }
}